package com.xiaozhi.component;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * 结构化日志记录组件
 * 用于记录聊天请求的详细信息，便于日志分析和监控
 */
@Component
@Slf4j
public class StructuredLogger {
    
    private final ObjectMapper objectMapper = new ObjectMapper();
    private static final DateTimeFormatter TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
    
    /**
     * 记录聊天请求开始
     * @param sessionId 会话ID
     * @param memoryId 内存ID
     * @param userMessage 用户消息
     * @param messageLength 消息长度
     */
    public void logChatRequestStart(String sessionId, Long memoryId, String userMessage, int messageLength) {
        Map<String, Object> logData = new HashMap<>();
        logData.put("event", "chat_request_start");
        logData.put("timestamp", LocalDateTime.now().format(TIMESTAMP_FORMATTER));
        logData.put("sessionId", sessionId);
        logData.put("memoryId", memoryId);
        logData.put("userMessage", truncateMessage(userMessage, 200)); // 截断长消息
        logData.put("messageLength", messageLength);
        logData.put("level", "INFO");
        
        logStructured(logData);
    }
    
    /**
     * 记录聊天请求成功
     * @param sessionId 会话ID
     * @param memoryId 内存ID
     * @param responseTime 响应时间（毫秒）
     * @param responseLength 响应长度
     * @param retryCount 重试次数
     */
    public void logChatRequestSuccess(String sessionId, Long memoryId, long responseTime, 
                                    int responseLength, int retryCount) {
        Map<String, Object> logData = new HashMap<>();
        logData.put("event", "chat_request_success");
        logData.put("timestamp", LocalDateTime.now().format(TIMESTAMP_FORMATTER));
        logData.put("sessionId", sessionId);
        logData.put("memoryId", memoryId);
        logData.put("responseTime", responseTime);
        logData.put("responseLength", responseLength);
        logData.put("retryCount", retryCount);
        logData.put("level", "INFO");
        
        logStructured(logData);
    }
    
    /**
     * 记录聊天请求失败
     * @param sessionId 会话ID
     * @param memoryId 内存ID
     * @param errorType 错误类型
     * @param errorMessage 错误消息
     * @param responseTime 响应时间（毫秒）
     * @param retryCount 重试次数
     */
    public void logChatRequestFailure(String sessionId, Long memoryId, String errorType, 
                                    String errorMessage, long responseTime, int retryCount) {
        Map<String, Object> logData = new HashMap<>();
        logData.put("event", "chat_request_failure");
        logData.put("timestamp", LocalDateTime.now().format(TIMESTAMP_FORMATTER));
        logData.put("sessionId", sessionId);
        logData.put("memoryId", memoryId);
        logData.put("errorType", errorType);
        logData.put("errorMessage", truncateMessage(errorMessage, 500));
        logData.put("responseTime", responseTime);
        logData.put("retryCount", retryCount);
        logData.put("level", "ERROR");
        
        logStructured(logData);
    }
    
    /**
     * 记录重试事件
     * @param sessionId 会话ID
     * @param attemptNumber 尝试次数
     * @param errorType 错误类型
     * @param delayMs 延迟时间
     */
    public void logRetryAttempt(String sessionId, int attemptNumber, String errorType, long delayMs) {
        Map<String, Object> logData = new HashMap<>();
        logData.put("event", "chat_retry_attempt");
        logData.put("timestamp", LocalDateTime.now().format(TIMESTAMP_FORMATTER));
        logData.put("sessionId", sessionId);
        logData.put("attemptNumber", attemptNumber);
        logData.put("errorType", errorType);
        logData.put("delayMs", delayMs);
        logData.put("level", "WARN");
        
        logStructured(logData);
    }
    
    /**
     * 记录API调用详情
     * @param sessionId 会话ID
     * @param apiEndpoint API端点
     * @param requestSize 请求大小
     * @param responseSize 响应大小
     * @param httpStatus HTTP状态码
     * @param responseTime 响应时间
     */
    public void logApiCall(String sessionId, String apiEndpoint, int requestSize, 
                          int responseSize, int httpStatus, long responseTime) {
        Map<String, Object> logData = new HashMap<>();
        logData.put("event", "api_call");
        logData.put("timestamp", LocalDateTime.now().format(TIMESTAMP_FORMATTER));
        logData.put("sessionId", sessionId);
        logData.put("apiEndpoint", apiEndpoint);
        logData.put("requestSize", requestSize);
        logData.put("responseSize", responseSize);
        logData.put("httpStatus", httpStatus);
        logData.put("responseTime", responseTime);
        logData.put("level", httpStatus >= 400 ? "ERROR" : "INFO");
        
        logStructured(logData);
    }
    
    /**
     * 记录用户行为
     * @param sessionId 会话ID
     * @param action 用户行为
     * @param details 详细信息
     */
    public void logUserAction(String sessionId, String action, Map<String, Object> details) {
        Map<String, Object> logData = new HashMap<>();
        logData.put("event", "user_action");
        logData.put("timestamp", LocalDateTime.now().format(TIMESTAMP_FORMATTER));
        logData.put("sessionId", sessionId);
        logData.put("action", action);
        logData.put("details", details);
        logData.put("level", "INFO");
        
        logStructured(logData);
    }
    
    /**
     * 记录系统事件
     * @param event 事件名称
     * @param details 事件详情
     */
    public void logSystemEvent(String event, Map<String, Object> details) {
        Map<String, Object> logData = new HashMap<>();
        logData.put("event", event);
        logData.put("timestamp", LocalDateTime.now().format(TIMESTAMP_FORMATTER));
        logData.put("details", details);
        logData.put("level", "INFO");
        
        logStructured(logData);
    }
    
    /**
     * 输出结构化日志
     * @param logData 日志数据
     */
    private void logStructured(Map<String, Object> logData) {
        try {
            String jsonLog = objectMapper.writeValueAsString(logData);
            String level = (String) logData.get("level");
            
            switch (level) {
                case "ERROR":
                    log.error("[STRUCTURED] {}", jsonLog);
                    break;
                case "WARN":
                    log.warn("[STRUCTURED] {}", jsonLog);
                    break;
                case "DEBUG":
                    log.debug("[STRUCTURED] {}", jsonLog);
                    break;
                default:
                    log.info("[STRUCTURED] {}", jsonLog);
                    break;
            }
        } catch (Exception e) {
            log.error("结构化日志记录失败: {}", e.getMessage());
        }
    }
    
    /**
     * 截断长消息
     * @param message 原始消息
     * @param maxLength 最大长度
     * @return 截断后的消息
     */
    private String truncateMessage(String message, int maxLength) {
        if (message == null) {
            return null;
        }
        
        if (message.length() <= maxLength) {
            return message;
        }
        
        return message.substring(0, maxLength) + "...";
    }
    
    /**
     * 生成会话ID
     * @return 会话ID
     */
    public String generateSessionId() {
        return "session_" + System.currentTimeMillis() + "_" + 
               Thread.currentThread().getId();
    }
}